//+------------------------------------------------------------------+
//|                                     MACD_RSI_MA_Strategy.mq5     |
//|                                     Copyright 2024, ForexExpert  |
//|                                             https://www.example.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, ForexExpert"
#property version   "1.00"
#property strict
#include <Trade\Trade.mqh>
CTrade trade;

//--- 输入参数

input double   totalRevenue = 500;        // 本次总收益
input double   openOrderNum = 15;        //  限制开单数
input double   LotSize      = 0.01;       // 交易手数
input int      StopLoss     = 10000;       // 止损点数
input int      TakeProfit   = 200;       // 止盈点数
input int      MA_Period    = 30;       // EMA周期
input int      RSI_Period   = 14;        // RSI周期
input int      MACD_Fast    = 12;        // MACD快线
input int      MACD_Slow    = 26;        // MACD慢线
input int      MACD_Signal  = 9;         // MACD信号线

//--- 全局变量
int    macdHandle, rsiHandle, maHandle;
double macdBuffer[], signalBuffer[], rsiBuffer[], maBuffer[];
datetime LastCloseTime;
bool EnableTrading = true;
bool SymbolOrder = true;


//+------------------------------------------------------------------+
//| 脚本：获取当前持仓浮动收益                                         |
//+------------------------------------------------------------------+
double getProfit()
  {
   double totalNetProfit = 0.0;

// 加载所有历史交易记录
   if(HistorySelect(0, TimeCurrent()))
     {
      int totalDeals = HistoryDealsTotal();
      for(int i = 0; i < totalDeals; i++)
        {
         ulong dealTicket = HistoryDealGetTicket(i);
         long dealType = HistoryDealGetInteger(dealTicket, DEAL_TYPE);

         // 仅统计平仓交易（DEAL_TYPE_BUY/SELL对应的平仓操作）
         if(dealType == DEAL_TYPE_SELL || dealType == DEAL_TYPE_BUY)
           {
            double profit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
            totalNetProfit += profit;
           }
        }
     }

   Print("累计盈利金额: ", totalNetProfit, " ", AccountInfoString(ACCOUNT_CURRENCY));
   return totalNetProfit;
  }

//+------------------------------------------------------------------+
//| 平仓盈利持仓函数                                                 |
//+------------------------------------------------------------------+
void CloseProfitablePositions()
  {
   for(int i = PositionsTotal()-1; i >= 0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionSelectByTicket(ticket))
        {
         string symbol = PositionGetString(POSITION_SYMBOL);
           {
            Print("平仓");

            trade.PositionClose(ticket);
           }
        }
     }
  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseProfitablePositions2()
  {
   double sl = PositionGetDouble(POSITION_SL);
   double tp = PositionGetDouble(POSITION_TP);
   double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   double volume = PositionGetDouble(POSITION_VOLUME);
// 平仓50%
   double closeVolume = NormalizeDouble(volume * 0.5, 2);
   trade.PositionClosePartial(_Symbol, closeVolume);

// 剩余仓位调整为止损保本
   double newSl = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? openPrice : openPrice;
   trade.PositionModify(_Symbol, newSl, tp);
  }


//+------------------------------------------------------------------+
//| 专家初始化函数                                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
// 初始化指标句柄
   macdHandle = iMACD(_Symbol, PERIOD_CURRENT, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE);
   rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
   maHandle = iMA(_Symbol, PERIOD_CURRENT, MA_Period, 0, MODE_EMA, PRICE_CLOSE);

// 设置指标缓冲区
   ArraySetAsSeries(macdBuffer, true);
   ArraySetAsSeries(signalBuffer, true);
   ArraySetAsSeries(rsiBuffer, true);
   ArraySetAsSeries(maBuffer, true);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| 专家逐笔处理函数                                                 |
//+------------------------------------------------------------------+
void OnTick()
  {
   OnTickOrder();
  }


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTickOrder()
  {
// 确保新K线且无持仓
//if(!IsNewBar() || PositionsTotal() > 0) return;

   if(!EnableTrading)
     {
      Print("交易已禁用！");
      CloseProfitablePositions2();
      return; // 直接退出，不执行交易逻辑
     }

   double balance = AccountInfoDouble(ACCOUNT_BALANCE);    // 余额

   double equity = AccountInfoDouble(ACCOUNT_EQUITY);      // 净值
   Print("交易！余额",balance);
   Print("交易！余额",equity);
   if(getProfit() - equity > totalRevenue)
     {

      CloseProfitablePositions();
      EnableTrading = false;
      return;
     }


   if(PositionsTotal()>openOrderNum)
     {
      return;
     }





// 更新指标数据
   CopyBuffer(macdHandle, MAIN_LINE, 0, 3, macdBuffer);
   CopyBuffer(macdHandle, SIGNAL_LINE, 0, 3, signalBuffer);
   CopyBuffer(rsiHandle, 0, 0, 3, rsiBuffer);
   CopyBuffer(maHandle, 0, 0, 3, maBuffer);

// 获取当前价格
   double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);

// 计算交易信号
   bool buySignal = CheckBuyCondition(currentPrice);
   bool sellSignal = CheckSellCondition(currentPrice);

// 执行交易
   if(buySignal)
      PlaceOrder(ORDER_TYPE_BUY);
   if(sellSignal)
      PlaceOrder(ORDER_TYPE_SELL);
  }

//+------------------------------------------------------------------+
//| 买入条件检查                                                     |
//+------------------------------------------------------------------+
bool CheckBuyCondition(double price)
  {
// 价格在MA上方
   bool maCondition = price > maBuffer[0];

// MACD金叉
   bool macdCondition = macdBuffer[1] < signalBuffer[1] &&
                        macdBuffer[0] > signalBuffer[0];

// RSI超卖回升
   bool rsiCondition = rsiBuffer[1] < 30 &&
                       rsiBuffer[0] > 30;

   return (maCondition && macdCondition && rsiCondition);
  }

//+------------------------------------------------------------------+
//| 卖出条件检查                                                     |
//+------------------------------------------------------------------+
bool CheckSellCondition(double price)
  {
// 价格在MA下方
   bool maCondition = price < maBuffer[0];

// MACD死叉
   bool macdCondition = macdBuffer[1] > signalBuffer[1] &&
                        macdBuffer[0] < signalBuffer[0];

// RSI超买回落
   bool rsiCondition = rsiBuffer[1] > 70 &&
                       rsiBuffer[0] < 70;

   return (maCondition && macdCondition && rsiCondition);
  }

//+------------------------------------------------------------------+
//| 下单函数                                                         |
//+------------------------------------------------------------------+
void PlaceOrder(ENUM_ORDER_TYPE orderType)
  {
   MqlTradeRequest request;
   MqlTradeResult  result;
   double entryPrice, sl, tp;

// 获取正确入场价格
   if(orderType == ORDER_TYPE_BUY)
     {
      entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // 使用Ask价买入
      sl = entryPrice - StopLoss * _Point;
      tp = entryPrice + TakeProfit * _Point;
     }
   else
     {
      entryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // 使用Bid价卖出
      sl = entryPrice + StopLoss * _Point;
      tp = entryPrice - TakeProfit * _Point;
     }

// 规范化价格到交易品种精度
   sl = NormalizeDouble(sl, _Digits);
   tp = NormalizeDouble(tp, _Digits);

// 添加止损有效性验证
   if(orderType == ORDER_TYPE_BUY && sl >= entryPrice)
     {
      Print("无效止损：买单止损应低于入场价");
      return;
     }
   if(orderType == ORDER_TYPE_SELL && sl <= entryPrice)
     {
      Print("无效止损：卖单止损应高于入场价");
      return;
     }

// 添加止损有效性验证
   if(orderType == ORDER_TYPE_BUY)
     {
      trade.Buy(LotSize, _Symbol, SymbolInfoDouble(_Symbol, SYMBOL_ASK), sl, tp, "PhaseEntry");
     }

// 添加止损有效性验证
   if(orderType == ORDER_TYPE_SELL)
     {
      // trade.Sell(LotSize, _Symbol, SymbolInfoDouble(_Symbol, SYMBOL_BID), sl, tp, "PhaseEntry");
     }
  }

//+------------------------------------------------------------------+
//| 新K线检测函数                                                    |
//+------------------------------------------------------------------+
bool IsNewBar()
  {
   static datetime lastBarTime;
   datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);

   if(lastBarTime != currentBarTime)
     {
      lastBarTime = currentBarTime;
      return true;
     }
   return false;
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
